//=============================================================================

#include <fstream>
#include <windows.h>
#include <gl/gl.h>
#include "../inc/aModel.h"
#include "../inc/aAux.h"

//=============================================================================

using namespace std;

//=============================================================================

aModel::aModel()
{
  currentVertexes = 0;
  drawSkeleton = 1;
  drawJointsAxis = 1;
  animationFps = 24;
  currentVertexes = 0;
  framesInterval = 1000/animationFps;
}

//=============================================================================

void aModel::asDrawSurface() const
{
  if (!draw)
    return;

  bool exist = skin.asIsExist();

  glPushMatrix();
  glTranslatef(origin.x, origin.y, origin.z);
	glTexCoordPointer(2, GL_FLOAT, 0, uv);
  glVertexPointer(3, GL_FLOAT, 0, currentVertexes);
  glNormalPointer(GL_FLOAT, 0, normals);

  if (exist)
    skin.asBindSkin();
  else
    glDisable(GL_TEXTURE_2D);

  if (drawPoints)
  {
    if (exist)
      glDisable(GL_TEXTURE_2D);

    glColor3ub(0, 255, 0);
	  glDrawArrays(GL_POINTS, 0, vertexesCount);

    if (exist)
      glEnable(GL_TEXTURE_2D);
  }
  if (drawLines)
  {
    if (exist || !drawPoints)
      glDisable(GL_TEXTURE_2D);

    glColor3ub(0, 0, 255);
    glDrawArrays(GL_LINES, 0, vertexesCount);

    if (exist || !drawPoints)
      glEnable(GL_TEXTURE_2D);
  }
  if (drawTriangles)
  {
    glColor3ub(color[0], color[1], color[2]);
	  glDrawArrays(GL_TRIANGLES, 0, vertexesCount);
  }
  if (drawBB && bb)
  {
    glDisable(GL_DEPTH_TEST);
    glEnable(GL_BLEND);
    glDisable(GL_TEXTURE_2D);
	  glLineWidth(3);

    glVertexPointer(3, GL_FLOAT, 0, bb);
    glColor4ub(0, 255, 0, 90);
    glDrawArrays(GL_TRIANGLES, 0, 36);
    glColor4ub(255, 0, 0, 255);
    glDrawArrays(GL_LINE_STRIP, 0, 36);
    glColor4ub(0, 0, 255, 255);
    glDrawArrays(GL_POINTS, 0, 36);
    
    glEnable(GL_TEXTURE_2D);
    glEnable(GL_DEPTH_TEST);
    glDisable(GL_BLEND);
	  glLineWidth(1);
  }
  if (drawSkeleton)
  {
    glDisable(GL_TEXTURE_2D);
    glDisable(GL_DEPTH_TEST);
    glPointSize(7);
      skel.asDrawSkeleton(0, drawJointsAxis);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_TEXTURE_2D);
    glPointSize(3);
  }
  if (drawOrigin)
  {
    glDisable(GL_TEXTURE_2D);
    glColor3ub(255, 0, 0);
    glBegin(GL_LINES);
      glVertex3f(0.0f, 0.0f, 0.0f);
      glVertex3f(1.0f, 0.0f, 0.0f);
    glEnd();
    glColor3ub(0, 255, 0);
    glBegin(GL_LINES);
      glVertex3f(0.0f, 0.0f, 0.0f);
      glVertex3f(0.0f, 1.0f, 0.0f);
    glEnd();
    glColor3ub(0, 0, 255);
    glBegin(GL_LINES);
      glVertex3f(0.0f, 0.0f, 0.0f);
      glVertex3f(0.0f, 0.0f, 1.0f);
    glEnd();
    glEnable(GL_TEXTURE_2D);
  }
  if (drawNormals)
    asDrawNormals();
  glPopMatrix();
}

//=============================================================================

void aModel::asSpawnMemory(unsigned int tCount)
{
  if (tCount <= 0)
    return;

  trianglesCount = tCount;
  vertexesCount = trianglesCount*3;

  vertexes = new float[vertexesCount*3];
  currentVertexes = new float[vertexesCount*3];
  uv = new float[vertexesCount*2];
  normals = new float[vertexesCount*3];
  
  memset(vertexes, 0, sizeof(float)*vertexesCount*3);
  memset(currentVertexes, 0, sizeof(float)*vertexesCount*3);
  memset(uv, 0, sizeof(float)*vertexesCount*2);
  memset(normals, 0, sizeof(float)*vertexesCount*3);
}

//=============================================================================

amlRet aModel::amLoadModel(const aString& path)
{
  if (path.asGetLength() <= 0)
    return MOD_NULLED_FILE_PATH;

  asRemoveSurfaceData();

  fstream file;

  file.open(path.asGetString(), ios_base::in | ios_base::binary);

  if (!file.is_open())
    return MOD_CANT_OPEN_MODEL_FILE_FOR_READING;

  file.read((char*)&trianglesCount, sizeof(trianglesCount));

  file.seekg(0, ios_base::end);
  long fileLength = file.tellg();
  const long iniCompare = sizeof(trianglesCount);
  long compare = sizeof(trianglesCount) + trianglesCount*24*sizeof(float);

  if (fileLength != compare)
  {
    trianglesCount = 0;
    file.close();

    return MOD_WRONG_MODEL_FILE_FORMAT;
  }
  else
    file.seekg(iniCompare);

  asSpawnMemory(trianglesCount);

  file.read((char*)vertexes, sizeof(float)*vertexesCount*3);
  file.read((char*)uv, sizeof(float)*vertexesCount*2);
  file.read((char*)normals, sizeof(float)*vertexesCount*3);

  file.close();
  
  asGetBB();
  amResetVertexesToBind();

  return MOD_DONE;
}

//=============================================================================

amlRet aModel::amLoadAnimation(const aString& path, const aString& name)
{
  if ((path.asGetLength() <= 0) || (name.asGetLength() <= 0))
    return MOD_NULLED_FILE_PATH;

  if (amHasAnimation(name))
    return MOD_ALREADY_HAS_THIS_ANIMATION;

  if (asIsNULL())
    return MOD_NO_GEOMETRY_DATA;

  fstream file;

  file.open(path.asGetString(), ios_base::in | ios_base::binary);

  if (!file.is_open())
    return MOD_CANT_OPEN_ANIMATION_FILE_FOR_READING;

  const unsigned int maxStringLength = 1024;
  bool res;
  char tmpChar[maxStringLength];
  unsigned int jointsCount;
  unsigned int nameLength, i;
  float framesCount;
  float* floatingPointer;

  file.read((char*)&framesCount, sizeof(float));
  file.read((char*)&jointsCount, sizeof(unsigned int));

  for (i = 0; i < jointsCount; ++i)
  {
    file.read((char*)&nameLength, sizeof(unsigned int));
    memset(tmpChar, 0, maxStringLength);
    file.read(tmpChar, nameLength);
    
    floatingPointer = new float[aJoint::matrixSize*unsigned int(framesCount)];
    file.read((char*)floatingPointer, magicSize*unsigned int(framesCount));
    res = skel.asAddAnimationToJoint(aString(tmpChar), name, floatingPointer, unsigned int(framesCount));

    if (!res)
      delete [] floatingPointer;
  }

  file.close();

  skel.asPrepareAnimation(name);
  hasAnimations.alAddItem()->data = name;

  return MOD_DONE;
}

//=============================================================================

amlRet aModel::amPlayAnimation(const aString& name, bool loop)
{
  if (name.asGetLength() <= 0)
    return MOD_BAD_ANIMATION_NAME;

  if (!skel.pubJoints.alGetFirstItem())
    return MOD_NO_SKELETON;

  aItem<aPlayAnimation>* tmpItem = playingAnimations.alGetFirstItem();

  while(tmpItem)
  {
    if (tmpItem->data.name == name)
      break;

    tmpItem = tmpItem->next;
  }

  if (!tmpItem)
  {
    aItem<aJoint*>* tmpJoint = skel.pubJoints.alGetFirstItem();
    aItem<aAnimationsTrack>* tmpAnim;

    while(tmpJoint)
    {
      tmpAnim = tmpJoint->data->ajGetAnimationByName(name);

      if (tmpAnim)
        break;

      tmpJoint = tmpJoint->next;
    }
    if (!tmpAnim)
      return MOD_NO_SUCH_ANIMATION;
    
    tmpItem = playingAnimations.alAddItem();
    tmpItem->data.framesCount = tmpAnim->data.framesCount;
    tmpItem->data.name = name;
    tmpItem->data.loop = loop;
  }
  else
    if (tmpItem->data.pause)
      tmpItem->data.pause = 0;
    else
      return MOD_ANIMATION_ALREADY_ON;

  return MOD_ANIMATION_STARTED;
}

//=============================================================================

unsigned int aModel::amGetAnimationFramesCount(const aString& name)
{
  if (name.asGetLength() <= 0)
    return 0;
  
  aItem<aPlayAnimation>* tmpItem = playingAnimations.alGetFirstItem();

  while(tmpItem)
  {
    if (tmpItem->data.name == name)
      return tmpItem->data.framesCount;

    tmpItem = tmpItem->next;
  }

  return 0;
}

//=============================================================================

bool aModel::amHasAnimation(const aString& name)
{
  if (name.asGetLength() <= 0)
    return 0;

  aItem<aString>* tmpString = hasAnimations.alGetFirstItem();

  while(tmpString)
  {
    if (tmpString->data == name)
      return 1;

    tmpString = tmpString->next;
  }

  return 0;
}

//=============================================================================

unsigned int aModel::amPauseAnimation(const aString& name)
{
  aItem<aPlayAnimation>* tmpPlay = amGetAnimationByName(name);

  if (!tmpPlay)
    return 0;

  if (tmpPlay->data.pause)
  {
    tmpPlay->data.pause = 0;

    return 1;
  }
  else
  {
    tmpPlay->data.pause = 1;

    return tmpPlay->data.currentFrame;
  }
}

//=============================================================================

void aModel::amSetAnimationFrame(const aString& name, unsigned int frame)
{
  if (!frame || (name.asGetLength() <= 0))
    return;

  aItem<aPlayAnimation>* tmpPlay = amGetAnimationByName(name);

  if (tmpPlay)
  {
    tmpPlay->data.currentFrame = frame;
    if (tmpPlay->data.pause)
    {
      tmpPlay->data.pause = 0;
      amAnimateModel();
      tmpPlay->data.pause = 1;
    }
  }
}

//=============================================================================

bool aModel::amIsAnimationPaused(const aString& name)
{
  if (name.asGetLength() <= 0)
    return 0;
  
  aItem<aPlayAnimation>* tmpPlay = amGetAnimationByName(name);

  if (tmpPlay)
    return tmpPlay->data.pause;
  
  return 0;
}

//=============================================================================

unsigned int aModel::amGetAnimationFrame(const aString& name)
{
  if (name.asGetLength() <= 0)
    return 0;

  aItem<aPlayAnimation>* tmpPlay = playingAnimations.alGetFirstItem();

  while(tmpPlay)
  {
    if (tmpPlay->data.name == name)
      return tmpPlay->data.currentFrame;

    tmpPlay = tmpPlay->next;
  }

  return 0;
}

//=============================================================================

void aModel::amGetJointsNames(aList<aString>& namesList)
{
  namesList.alRemoveItems();

  aItem<aJoint*>* tmpJoint = skel.pubJoints.alGetFirstItem();

  while(tmpJoint)
  {
    namesList.alAddItem()->data = tmpJoint->data->name;

    tmpJoint = tmpJoint->next;
  }
}

//=============================================================================

size_t aModel::amGetAnimationDataVolume() const
{
  size_t res = 0;

  if (hasAnimations.alGetCount() <= 0)
    return 0;

  aItem<aJoint*>* tmpJoint = skel.pubJoints.alGetFirstItem();
  aItem<aAnimationsTrack>* tmpAnim = 0;
  int jCount = skel.pubJoints.alGetCount();
  size_t sizeSize = sizeof(size_t);
  size_t charSize = tmpJoint->data->name.asGetCharSize();
  size_t intSize = sizeof(int);
  size_t floatSize = sizeof(float);

  res += sizeSize*jCount;//joint name length
  res += sizeof(int)*jCount;//tracks count
  while(tmpJoint)
  {
    res += tmpJoint->data->name.asGetLength()*charSize;//name
    tmpAnim = tmpJoint->data->track.alGetFirstItem();
    while(tmpAnim)
    {
      res += intSize*2;//track name length & framesCount
      res += charSize*tmpAnim->data.caption.asGetLength();//track name
      res += floatSize*tmpJoint->data->matrixSize*tmpAnim->data.framesCount;//matrix data
      tmpAnim = tmpAnim->next;
    }

    tmpJoint = tmpJoint->next;
  }

  return res;
}

//=============================================================================

amlRet aModel::amCollectAnimationsData(void* data, size_t wholeSize) const
{
  if (!data)
    return MOD_COL_BAD_DATA_POINTER;

  if (wholeSize <= 0)
    return MOD_COL_BAD_DATA_VOLUME;

  aItem<aJoint*>* tmpJoint = skel.pubJoints.alGetFirstItem();

  if (!tmpJoint)
    return MOD_COL_NO_SKEL_JOINTS_DATA;

  size_t shift = 0;
  char* tmpPointer = (char*)data;
  size_t tmpLength;
  size_t sizeSize = sizeof(size_t);
  size_t charSize = tmpJoint->data->name.asGetCharSize();
  size_t intSize = sizeof(int);
  size_t floatSize = sizeof(float);
  int tmpCount;
  aItem<aAnimationsTrack>* tmpAnim = 0;

  while(tmpJoint)
  {
    tmpLength = tmpJoint->data->name.asGetLength();
    memcpy(&tmpPointer[shift], &tmpLength, sizeSize);
    shift += sizeSize;

    memcpy(&tmpPointer[shift], tmpJoint->data->name.asGetString(), charSize*tmpLength);
    shift += charSize*tmpLength;

    tmpCount = tmpJoint->data->track.alGetCount();
    memcpy(&tmpPointer[shift], &tmpCount, intSize);
    shift += intSize;

    tmpAnim = tmpJoint->data->track.alGetFirstItem();
    while(tmpAnim)
    {
      memcpy(&tmpPointer[shift], &tmpAnim->data.framesCount, intSize);
      shift += intSize;

      tmpLength = tmpAnim->data.caption.asGetLength();
      memcpy(&tmpPointer[shift], &tmpLength, sizeSize);
      shift += sizeSize;

      memcpy(&tmpPointer[shift], tmpAnim->data.caption.asGetString(), charSize*tmpLength);
      shift += charSize*tmpLength;

      memcpy(&tmpPointer[shift], tmpAnim->data.mtx, floatSize*tmpJoint->data->matrixSize*tmpAnim->data.framesCount);
      shift += floatSize*tmpJoint->data->matrixSize*tmpAnim->data.framesCount;

      tmpAnim = tmpAnim->next;
    }

    tmpJoint = tmpJoint->next;
  }

  return MOD_DONE;
}

//=============================================================================

void aModel::asRemoveSurfaceData()
{
  if (asIsNULL())
    return;

  if (vertexesCount)
  {
    if (vertexes)
    {
      delete [] vertexes;
      
      vertexes = 0;
    }
    if (uv)
    {
      delete [] uv;

      uv = 0;
    }
    if (currentVertexes)
    {
      delete [] currentVertexes;

      currentVertexes = 0;
    }
    if (normals)
    {
      delete [] normals;

      normals = 0;
    }
  }
  bbMax.avSet(0.0f, 0.0f, 0.0f);
  bbMin.avSet(0.0f, 0.0f, 0.0f);
  bbDiff.avSet(0.0f, 0.0f, 0.0f);
  vertexesCount = 0;
  trianglesCount = 0;
}

//=============================================================================

void aModel::amDestroyModel()
{
  asRemoveSurfaceData();
  asRemoveSkinData();
  amRemoveSkeletonData();
  amRemoveAnimationsData();
}

//=============================================================================

void aModel::amAnimateModel()
{
  aItem<aPlayAnimation>* tmpPlay = playingAnimations.alGetFirstItem(),* tmpPlay2 = 0;

  if (!tmpPlay)
    return;

  aItem<aAnimationsTrack>* tmpAnim;
  aItem<aJoint*>* tmpJoint;
  size_t magicSize2;
  DWORD currentFrameTime, framesDifference;
  bool end = 0;

  while(tmpPlay)
  {
    if (tmpPlay->data.pause)
    {
      tmpPlay = tmpPlay->next;

      continue;
    }
    if (tmpPlay->data.currentFrame < tmpPlay->data.framesCount)
    {
      currentFrameTime = GetTickCount();
      framesDifference = currentFrameTime - lastFrameTime;
      if (framesDifference >= framesInterval)
      {
        magicSize2 = tmpPlay->data.currentFrame*aJoint::matrixSize;
        tmpJoint = skel.pubJoints.alGetFirstItem();
        while(tmpJoint)
        {
          tmpAnim = tmpJoint->data->ajGetAnimationByName(tmpPlay->data.name);

          if (tmpAnim)
            memcpy(tmpJoint->data->currentMatrix, &tmpAnim->data.mtx[magicSize2], magicSize);
          else
            tmpJoint->data->ajCopyDataToCurrentMatrix();

          tmpJoint = tmpJoint->next;
        }
        amCalculateVertexes();
        lastFrameTime = currentFrameTime;
        ++(tmpPlay->data.currentFrame);
      }
    }
    else
      if (tmpPlay->data.loop)
        tmpPlay->data.currentFrame = 0;
      else
      {
        tmpPlay2 = tmpPlay->next;
        end = 1;
        playingAnimations.alRemoveItem(tmpPlay);
      }

    if (end)
    {
      end = 0;

      if (tmpPlay2)
        tmpPlay = tmpPlay2;
      else
        break;
    }
    else
      tmpPlay = tmpPlay->next;
  }
}

//=============================================================================

void aModel::amCalculateVertexes()
{
  unsigned long i, num;
  aItem<aJoint*>* firstJoint = skel.pubJoints.alGetFirstItem();
  aItem<aJoint*>* tmpJoint;
  aVector tmpVector, tmpVector4;
  float lenI, lenJ, lenK;
  float diff;

  amResetVertexesToNULL();

  for (i = 0; i < vertexesCount; ++i)
  {
    tmpJoint = firstJoint;
    while(tmpJoint)
    {
      if (!aAux::aaGetInstance().aaCompareFloat(tmpJoint->data->weights[i], 0.0f))
      {
        num = i*3;
        //aVector vec(vertexes[num], vertexes[num + 1], vertexes[num + 2]);
        //aMatrix4 mtx(tmpJoint->data->ijk[0], tmpJoint->data->ijk[1], tmpJoint->data->ijk[2], tmpJoint->data->position);

        //mtx = aAux::aaGetInstance().aaGetInverse(mtx);

        //vec = aAux::aaGetInstance().aaMultiply(vec, mtx);

        //aVector ii(tmpJoint->data->currentMatrix[0], tmpJoint->data->currentMatrix[1], tmpJoint->data->currentMatrix[2]);
        //aVector jj(tmpJoint->data->currentMatrix[4], tmpJoint->data->currentMatrix[5], tmpJoint->data->currentMatrix[6]);
        //aVector kk(tmpJoint->data->currentMatrix[8], tmpJoint->data->currentMatrix[9], tmpJoint->data->currentMatrix[10]);
        //aVector pp(tmpJoint->data->currentMatrix[12], tmpJoint->data->currentMatrix[13], tmpJoint->data->currentMatrix[14]);
        //aMatrix4 mtx2(ii, jj, kk, pp);

        //vec = aAux::aaGetInstance().aaMultiply(vec, mtx2);
        //vec = aAux::aaGetInstance().aaMultiply(vec, tmpJoint->data->weights[i]);

        //currentVertexes[num] += vec.x;
        //currentVertexes[num + 1] += vec.y;
        //currentVertexes[num + 2] += vec.z;

        tmpVector4.x = vertexes[num] - tmpJoint->data->bindPosition.x;
        tmpVector4.y = vertexes[num + 1] - tmpJoint->data->bindPosition.y;
        tmpVector4.z = vertexes[num + 2] - tmpJoint->data->bindPosition.z;

        //project tmpVector4 on tmpJoint->data->bindIJK[0]
        diff = (tmpVector4.x*tmpJoint->data->bindIJK[0].x + tmpVector4.y*tmpJoint->data->bindIJK[0].y + tmpVector4.z*tmpJoint->data->bindIJK[0].z)/tmpJoint->data->bindIJKValue[0];
        tmpVector.x = tmpJoint->data->bindIJK[0].x*diff;
        tmpVector.y = tmpJoint->data->bindIJK[0].y*diff;
        tmpVector.z = tmpJoint->data->bindIJK[0].z*diff;//result of projection
        lenI = sqrt(tmpVector.x*tmpVector.x + tmpVector.y*tmpVector.y + tmpVector.z*tmpVector.z);//getting magnitude of tmpVector
        //now checking: is tmpVector lies on tmpJoint->data->bindIJK[0] (we need the sign. Actually in which part of axis vector lies: positive of negative)
        if (!aAux::aaGetInstance().aaCompareFloat(lenI + aAux::aaGetInstance().aaGetLength(tmpJoint->data->bindIJK[0], tmpVector), sqrt(tmpJoint->data->bindIJKValue[0])))
          lenI = -lenI;

        //project tmpVector4 on tmpJoint->data->bindIJK[1]
        diff = (tmpVector4.x*tmpJoint->data->bindIJK[1].x + tmpVector4.y*tmpJoint->data->bindIJK[1].y + tmpVector4.z*tmpJoint->data->bindIJK[1].z)/tmpJoint->data->bindIJKValue[1];
        tmpVector.x = tmpJoint->data->bindIJK[1].x*diff;
        tmpVector.y = tmpJoint->data->bindIJK[1].y*diff;
        tmpVector.z = tmpJoint->data->bindIJK[1].z*diff;//result of projection
        lenJ = sqrt(tmpVector.x*tmpVector.x + tmpVector.y*tmpVector.y + tmpVector.z*tmpVector.z);//getting magnitude of tmpVector
        //now checking: is tmpVector lies on tmpJoint->data->bindIJK[1] (we need the sign. Actually in which part of axis vector lies: positive of negative)
        if (!aAux::aaGetInstance().aaCompareFloat(lenJ + aAux::aaGetInstance().aaGetLength(tmpJoint->data->bindIJK[1], tmpVector), sqrt(tmpJoint->data->bindIJKValue[1])))
          lenJ = -lenJ;

        //project tmpVector4 on tmpJoint->data->bindIJK[2]
        diff = (tmpVector4.x*tmpJoint->data->bindIJK[2].x + tmpVector4.y*tmpJoint->data->bindIJK[2].y + tmpVector4.z*tmpJoint->data->bindIJK[2].z)/tmpJoint->data->bindIJKValue[2];
        tmpVector.x = tmpJoint->data->bindIJK[2].x*diff;
        tmpVector.y = tmpJoint->data->bindIJK[2].y*diff;
        tmpVector.z = tmpJoint->data->bindIJK[2].z*diff;//result of projection
        lenK = sqrt(tmpVector.x*tmpVector.x + tmpVector.y*tmpVector.y + tmpVector.z*tmpVector.z);//getting magnitude of tmpVector
        //now checking: is tmpVector lies on tmpJoint->data->bindIJK[2] (we need the sign. Actually in which part of axis vector lies: positive of negative)
        if (!aAux::aaGetInstance().aaCompareFloat(lenK + aAux::aaGetInstance().aaGetLength(tmpJoint->data->bindIJK[2], tmpVector), sqrt(tmpJoint->data->bindIJKValue[2])))
          lenK = -lenK;
        
        //here is final additions to vertex in it's bind position;
        currentVertexes[num] += (tmpJoint->data->currentMatrix[12] + tmpJoint->data->currentMatrix[0]*lenI + tmpJoint->data->currentMatrix[4]*lenJ + tmpJoint->data->currentMatrix[8]*lenK)*tmpJoint->data->weights[i];
        currentVertexes[num + 1] += (tmpJoint->data->currentMatrix[13] + tmpJoint->data->currentMatrix[1]*lenI + tmpJoint->data->currentMatrix[5]*lenJ + tmpJoint->data->currentMatrix[9]*lenK)*tmpJoint->data->weights[i];
        currentVertexes[num + 2] += (tmpJoint->data->currentMatrix[14] + tmpJoint->data->currentMatrix[2]*lenI + tmpJoint->data->currentMatrix[6]*lenJ + tmpJoint->data->currentMatrix[10]*lenK)*tmpJoint->data->weights[i];
      }
      tmpJoint = tmpJoint->next;
    }
  }

  //BEWARE: there is no bounding box recalculation! Use asGetBB() to get it;
}

//=============================================================================

void aModel::asDrawNormals() const
{
  unsigned long num;

  glDisable(GL_TEXTURE_2D);
  glColor3ub(255, 0, 0);
  for (unsigned long i = 0; i < vertexesCount; ++i)
  {
    num = i*3;
    glBegin(GL_LINES);
      glVertex3f(currentVertexes[num], currentVertexes[num + 1], currentVertexes[num + 2]);
      glVertex3f(currentVertexes[num] + normals[num], currentVertexes[num + 1] + normals[num + 1], currentVertexes[num + 2] + normals[num + 2]);
    glEnd();
  }
  glEnable(GL_TEXTURE_2D);
}

//=============================================================================

aItem<aPlayAnimation>* aModel::amGetAnimationByName(const aString& name)
{
  if (name.asGetLength() <= 0)
    return 0;

  aItem<aPlayAnimation>* tmpPlay = playingAnimations.alGetFirstItem();

  while(tmpPlay)
  {
    if (tmpPlay->data.name == name)
      return tmpPlay;

    tmpPlay = tmpPlay->next;
  }

  return 0;
}

//=============================================================================

aModel::~aModel()
{
  amDestroyModel();
}

//=============================================================================
